#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <functional>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include "InetAddr.hpp"
#include "ThreadPool.hpp"
#include "LockGuard.hpp"

using task_t = std::function<void()>;

class Route
{
public:
    Route()
    {
        pthread_mutex_init(&_mutex,nullptr);
    }
    // 检查用户是否在 在线列表中
    void CheckOnlineUser(InetAddr& who)
    {
        LockGuard lockguard(&_mutex);
        for(auto& user : _online_user)
        {
            // 需要重载
            if(user == who) 
            {
                LOG(DEBUG,"[%s] is exists\n",who.AddrStr().c_str());
                return;
            }
        }
        LOG(DEBUG,"[%s] is not exists,add it\n",who.AddrStr().c_str());
        _online_user.push_back(who);
    }
    // for test(移除用户)
    void Offline(InetAddr& who)
    {
        LockGuard lockguard(&_mutex);
        // 删除需要迭代器
        auto iter = _online_user.begin();
        for(;iter != _online_user.end();iter++)
        {
            if(*iter == who)
            {
                LOG(DEBUG,"[%s] is offline\n",who.AddrStr().c_str());
                _online_user.erase(iter);
                break;
            }
        }
    }
    // 转发消息函数具体实现
    void ForwardHelper(int sockfd,const std::string& message,InetAddr who)
    {
        LockGuard lockguard(&_mutex);
        std::string send_message = "[" + who.AddrStr() + "]# " + message;
        
        for(auto& user : _online_user)
        {
            struct sockaddr_in peer = user.Addr();
            // 无IP和端口
            // LOG(DEBUG,"Forward message to %s,message is %s\n",user.AddrStr().c_str(),message.c_str());
            // ::sendto(sockfd,message.c_str(),message.size(),0,(struct sockaddr*)&peer,sizeof(peer));
            LOG(DEBUG,"Forward message to %s,message is %s\n",user.AddrStr().c_str(),send_message.c_str());
            ::sendto(sockfd,send_message.c_str(),send_message.size(),0,(struct sockaddr*)&peer,sizeof(peer));
        }
    }
    // 转发
    void Forward(int sockfd,const std::string& message,InetAddr& who)
    {
        // 1.该用户是否在 在线用户列表中呢？如果在忽略；如果不在，自动添加到_online_user
        CheckOnlineUser(who);

        // 1.1 message == "QUIT" "Q"
        if(message == "QUIT" || message == "Q")
        {
            Offline(who);
        }
        // 2.who一定在_online_user里面
        // ForwardHelper(sockfd,message);
        task_t t = std::bind(&Route::ForwardHelper,this,sockfd,message,who);
        ThreadPool<task_t>::GetInstance()->Equeue(t);
    }
    ~Route()
    {
        pthread_mutex_destroy(&_mutex);
    }
private:
    std::vector<InetAddr> _online_user;
    pthread_mutex_t _mutex;
};